package com.thingsgrid.firmware.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mongodb.client.result.UpdateResult;
import com.thingsgrid.device.entity.Product;
import com.thingsgrid.firmware.entity.Firmware;
import com.thingsgrid.firmware.entity.FirmwareInfo;
import com.thingsgrid.firmware.entity.FirmwareUpgradeMode;
import com.thingsgrid.firmware.entity.FirmwareUpgradeRecord;
import com.thingsgrid.firmware.service.IFirmwareService;
import lombok.AllArgsConstructor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.LookupOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;

@Service
@AllArgsConstructor
public class FirmwareServiceImpl implements IFirmwareService {
	private MongoTemplate template;


	@Override
	public List<Map> getDevicelist(Page page, String methodid, Integer stats) {
		LookupOperation lookupToLots = LookupOperation.newLookup().
			from("device").//关联表名 lots
			localField("device_id").//关联字段
			foreignField("device_id").//主表关联字段对应的次表字段
			as("d");//查询结果集合名
		Criteria criteria = new Criteria();
		criteria.where("1=1");
		if (methodid != null && methodid != "") {
			criteria.and("methods_id").is(methodid);
		}

		if (stats < 100) {
			criteria.and("upgrade_stats").is(stats);
		}
		AggregationOperation unwind = Aggregation.unwind("d");
		AggregationOperation match = Aggregation.match(criteria);
		AggregationOperation project = Aggregation.project("d.device_name", "upgrade_time", "old_firmware_version", "new_firmware_version", "upgrade_stats").andExclude("_id").andExclude("d._id");
		AggregationOperation limit = Aggregation.limit(page.getSize());

		AggregationOperation skip = Aggregation.skip((page.getCurrent() - 1) * page.getSize());
		Aggregation aggregation = Aggregation.newAggregation(lookupToLots, unwind, match, project, skip, limit);
		AggregationResults<Map> list = template.aggregate(aggregation, "firmware_upgrade_record", Map.class);
		List<Map> re = list.getMappedResults();
		return re;
	}

	@Override
	public Map getFirmware(Page page, String product_type, String firmware_name, String product_name) {
		//查询符合条件的firmware_id
		LookupOperation lookupToLots = LookupOperation.newLookup().
			from("product").//关联表名 lots
			localField("product_id").//关联字段
			foreignField("product_id").//主表关联字段对应的次表字段
			as("p");//查询结果集合名

		Pattern pattern_firmware = Pattern.compile("^.*" + firmware_name + ".*$", Pattern.CASE_INSENSITIVE);
		Pattern pattern_pro_type = Pattern.compile("^.*" + product_type + ".*$", Pattern.CASE_INSENSITIVE);
		Pattern pattern_pro_name = Pattern.compile("^.*" + product_name + ".*$", Pattern.CASE_INSENSITIVE);
		Criteria criteria = new Criteria();
		criteria.where("1=1");
		if (firmware_name != null && product_name != "") {
			criteria.and("firmware_name").regex(pattern_firmware);
		}
		if (product_type != null && product_type != "") {
			criteria.and("p.product_type_id").regex(pattern_pro_type);
		}
		if (product_name != null && product_name != "") {
			criteria.and("p.product_name").regex(pattern_pro_name);
		}
		AggregationOperation unwind = Aggregation.unwind("p");
		AggregationOperation match = Aggregation.match(criteria);
		AggregationOperation project = Aggregation.project("firmware_id", "firmware_name", "firmware_version", "p.product_type_id").andExclude("_id");

		Aggregation aggregation = Aggregation.newAggregation(lookupToLots, unwind, match, project);
		AggregationResults<Map> list = template.aggregate(aggregation, "firmware", Map.class);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < list.getMappedResults().size(); i++) {
			if (sb.length() > 0) {
				sb.append(",");
			}
			sb.append(list.getMappedResults().get(i).get("firmware_id"));
		}
		Criteria c = new Criteria();
		List<String> result = Arrays.asList(sb.toString().split(","));

		//以升级方式表为主表 并选出最终的数据
		c.where("1=1");
		c.and("firmware_id").in(result);
		c.and("isdelete").is(0);
		Map<String, Object> map = new HashMap();
		List<FirmwareInfo> infolist = new ArrayList<>();
		List<FirmwareUpgradeMode> modeList = template.find(new Query(c).skip((page.getCurrent() - 1) * page.getSize()).limit((int) page.getSize()), FirmwareUpgradeMode.class, "firmware_upgrade_mode");
		for (FirmwareUpgradeMode mode : modeList) {
			Integer totalRecord = (int) template.count(new Query(Criteria.where("methods_id").is(mode.getMethodId())), FirmwareUpgradeRecord.class, "firmware_upgrade_record");

			Integer successRecord = (int) template.count(new Query(Criteria.where("methods_id").is(mode.getMethodId()).and("upgrade_stats").is(1)), FirmwareUpgradeRecord.class, "firmware_upgrade_record");

			Integer failRecord = (int) template.count(new Query(Criteria.where("methods_id").is(mode.getMethodId()).and("upgrade_stats").is(0)), FirmwareUpgradeRecord.class, "firmware_upgrade_record");
			FirmwareInfo firmwareInfo = new FirmwareInfo();
			firmwareInfo.setMethodId(mode.getMethodId());
			firmwareInfo.setFirmwareId(mode.getFirmwareId());
			firmwareInfo.setUpgradeState(mode.getUpgradeState());
			Firmware firmware = template.findOne(new Query(Criteria.where("firmware_id").is(mode.getFirmwareId())), Firmware.class, "firmware");
			Product p = template.findOne(new Query(Criteria.where("product_id").is(firmware.getProductId())), Product.class, "product");
			firmwareInfo.setProduct_type(p.getProductTypeId());
			firmwareInfo.setFirmwareVersion(firmware.getFirmwareVersion());
			firmwareInfo.setUpgradeNum(totalRecord);
			firmwareInfo.setFirmwareName(firmware.getFirmwareName());
			firmwareInfo.setSuccessUpgrade(successRecord);
			firmwareInfo.setFailUpgrade(failRecord);
			infolist.add(firmwareInfo);
		}
		int totalNum = template.find(new Query(c), FirmwareUpgradeMode.class, "firmware_upgrade_mode").size();
		map.put("total", totalNum);
		map.put("info", infolist);
		return map;
	}

	@Override
	public UpdateResult deleteRecord(String methedId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("method_id").is(methedId));
		Update update = new Update();
		update.set("isdelete", 1);
		UpdateResult mode = template.updateMulti(query, update, "firmware_upgrade_mode");
		return mode;
	}

	@Override
	public void updateDeviceState(String deviceId, String productId, String firmware_version) {
		Query query = new Query();
		query.addCriteria(Criteria.where("device_id").is(deviceId).and("product_id").is(productId));
		Update update = new Update();
		update.set("firmware_version", firmware_version);
		template.updateMulti(query, update, "device");
	}
	@Override
	public void updateUpgradeRecordState(String upgrade_id, Integer stats) {
		Query query = new Query();
		query.addCriteria(Criteria.where("upgrade_id").is(upgrade_id));
		Update update = new Update();
		update.set("upgrade_stats",stats);
		template.updateMulti(query,update,"firmware_upgrade_record");
	}
}
